﻿#include "CConsoleLib.h"


CControl::CControl()
{
	memset(m_szChar, 0, MAX_PATH);
	m_hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	m_hIn = GetStdHandle(STD_INPUT_HANDLE);      //获得标准输入设备句柄 
//	GetConsoleScreenBufferInfoEx(m_hOut, &m_bInfo); // 获取窗口缓冲区信息

	//默认控件的显示范围
	m_rRect.Left = 0;
	m_rRect.Top = 0;
	m_rRect.Right = 0; //右边和底边为相对距离
	m_rRect.Bottom = 0;
	m_iPos = 0;
	m_iMax = 100; 
	m_vScrollbar = FALSE;
	m_hScrollbar = FALSE; //默认没有滚动条
}
void CControl::Highlight(int i)
{

}
void CControl::Show()
{
	COORD posShadow = { m_rRect.Left , m_rRect.Top };
	DWORD dwXx = 0;
	WriteConsoleOutputCharacterA(m_hOut, m_szChar, m_rRect.Right, posShadow, &dwXx);
	return;
}

int CControl::Proc(int lEvent, LPARAM  lPar)
{
	return 0;
}
void CControl::SetRect(SMALL_RECT *re)
{
	m_rRect.Left = re->Left;
	m_rRect.Top = re->Top;
	m_rRect.Right = re->Right;
	m_rRect.Bottom = re->Bottom;
}
void CControl::GetRect(SMALL_RECT *re)
{
	re->Left = m_rRect.Left;
	re->Top = m_rRect.Top;
	re->Right = m_rRect.Right;
	re->Bottom = m_rRect.Bottom;
}
void CControl::GetTitle(char *buf)
{
	buf = m_szChar;
}
void CControl::SetTitle(char *buf)
{
	sprintf_s(m_szChar, MAX_PATH, "%s", buf);
}
void CControl::ScrollbarShow()
{
	COORD cTemp = { 0 };
	cTemp.X = m_rRect.Left + m_rRect.Right - 2;
	cTemp.Y = m_rRect.Top;
	DWORD dwXx = 0;
	int pos = 1;
	pos = GetScrollBlock();
	for (int i = 0; i < m_rRect.Bottom; i++)
	{
		if (i == pos)
		{
			FillConsoleOutputAttribute(m_hOut, m_wHighlight_color, 2, cTemp, &dwXx);
			WriteConsoleOutputCharacterW(m_hOut, L"▓", 1, cTemp, &dwXx);
		}
		else
		{
			WriteConsoleOutputCharacterW(m_hOut, L" ", 1, cTemp, &dwXx);
			FillConsoleOutputAttribute(m_hOut, m_wGeneral_color, 2, cTemp, &dwXx);
		}
		if (i == 0)
		{
			WriteConsoleOutputCharacterA(m_hOut, "△", 2, cTemp, &dwXx);
		}
		if (i == m_rRect.Bottom - 1)
		{
			WriteConsoleOutputCharacterA(m_hOut, "▽", 2, cTemp, &dwXx);
		}
		cTemp.Y++;
	}
}
void CControl::ScrollbarSet(int iPos)
{
	m_iPos = iPos;
}
void CControl::SetScrollRange(int nBar, int nMaxPos, BOOL bRedraw)
{
	m_iMax = nMaxPos; //先只设置竖向滚动条
}
void CControl::SetScrollPos(int ipos)
{
	m_iPos = ipos;
	Show();
}
int CControl::GetScrollBlock()
{
	//根据当前POS位置，来计算划块所在坐标，可用来显示或返给过程使用
	float f1 = ceil((float)m_iMax / (float)(m_rRect.Bottom - 2));
	float f2 = (float)m_iPos / f1;
	return ceil(f2);   //每单位长度能用到的POS

}
CControl::~CControl()
{

}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////


CProgressBar::CProgressBar(int x, int y, int weight, int height)
{
	m_iProgress = 0;
	m_att0 = BACKGROUND_INTENSITY; // 阴影属性
	m_att1 = FOREGROUND_RED | BACKGROUND_BLUE;

	COORD cTemp = { 0 };
	DWORD dwXx = 0;

	m_rRect.Left = x;
	m_rRect.Top = y;
	m_rRect.Right = weight;
	m_rRect.Bottom = height;
	cTemp.X = m_rRect.Left;
	cTemp.Y = m_rRect.Top;
	//填充一个100时的完整条
	FillConsoleOutputAttribute(m_hOut, m_att0, m_rRect.Right, cTemp, &dwXx);
	
}
CProgressBar::CProgressBar(int lag, int x, int y, int weight, int height)
{
	m_iProgress = lag;
	m_att0 = BACKGROUND_INTENSITY; // 阴影属性
	m_att1 = FOREGROUND_RED | BACKGROUND_BLUE;

	COORD cTemp = { 0 };
	DWORD dwXx = 0;

	m_rRect.Left = x;
	m_rRect.Top = y;
	m_rRect.Right = weight;
	m_rRect.Bottom = height;
	cTemp.X = m_rRect.Left;
	cTemp.Y = m_rRect.Top;
	//填充一个100时的完整条
	FillConsoleOutputAttribute(m_hOut, m_att0, m_rRect.Right, cTemp, &dwXx);

}
void CProgressBar::SetProgress(int lag)
{
	m_iProgress = lag;
}

void CProgressBar::Show()
{
	
	DWORD dwXx = 0;
	BOOL bResult = FALSE;
	COORD cTemp = { 0 };

	cTemp.X = m_rRect.Left;
	cTemp.Y = m_rRect.Top;
	//根据进度来输出字符个数
	wmemset((WCHAR *)m_szChar,L'□', m_rRect.Right * m_iProgress / 100  / 2);
	for (int i = 0; i < m_rRect.Bottom; i ++)
	{
		bResult = FillConsoleOutputAttribute(m_hOut, m_att1, m_rRect.Right * m_iProgress / 100, cTemp, &dwXx);
		bResult = WriteConsoleOutputCharacterW(m_hOut, (WCHAR *)m_szChar, strlen(m_szChar) / 2, cTemp, &dwXx);
		cTemp.X = m_rRect.Left + m_rRect.Right * m_iProgress / 100;
		cTemp.Y = m_rRect.Top;
		//输出进度数字
		sprintf_s(m_szChar, MAX_PATH, "%d％", m_iProgress);
		bResult = FillConsoleOutputAttribute(m_hOut, FOREGROUND_RED | FOREGROUND_INTENSITY, strlen(m_szChar), cTemp, &dwXx);
		bResult = WriteConsoleOutputCharacterA(m_hOut, m_szChar, strlen(m_szChar), cTemp, &dwXx);
		memset(m_szChar, 0, MAX_PATH);
	}
	
}
//////////////////////////////////////////////////////////////////////////
//静态文本控件
CStaticText::CStaticText(char * buff, int x, int y, int weight, int height)
{
	sprintf_s(m_szChar, MAX_PATH, "%s", buff);
	m_rRect.Left = x;
	m_rRect.Top = y;
	m_rRect.Right = weight;
	m_rRect.Bottom = height;
}
CStaticText::CStaticText(int x, int y, int weight, int height)
{
	sprintf_s(m_szChar, MAX_PATH, "%s", " ");
	m_rRect.Left = x;
	m_rRect.Top = y;
	m_rRect.Right = weight;
	m_rRect.Bottom = height;
}
int CStaticText::Proc(int lEvent, LPARAM lPar)
{
	//根据事件每个控件自己处理自己的
	WORD att1 = 0;
	COORD cTemp = { 0 };
	cTemp.X = m_rRect.Left;
	cTemp.Y = m_rRect.Top;
	DWORD dxx = 0;
	ReadConsoleOutputAttribute(m_hOut,&att1,1,cTemp,&dxx);
	//改变一下颜色
	FillConsoleOutputAttribute(m_hOut,att1 | FOREGROUND_INTENSITY,m_rRect.Right,cTemp, &dxx);

	return 1;
}
void CStaticText::Show()
{
	COORD posShadow = { m_rRect.Left , m_rRect.Top };
	DWORD dwXx = 0;
	WriteConsoleOutputCharacterA(m_hOut, m_szChar, m_rRect.Right,posShadow, &dwXx);
}


//////////////////////////////////////////////////////////////////////////
//盒子控件
// 

CDrawBox::CDrawBox(int x, int y, int weight, int height)
{
	m_rRect.Left = x;
	m_rRect.Top = y;
	m_rRect.Right = weight;
	m_rRect.Bottom = height + 4; 
	m_wGeneral_color = 0; //本来的颜色

}

CDrawBox::~CDrawBox()
{
	CloseHandle(m_hOut);
}

//放入的控件及位置
void CDrawBox::Inset(CControl &control,int x, int y)
{
	//包含别的控件进来，每包含一个需要记录下控件信息，以及自身范围的变化
	child_control_info.push_back(&control);
	SMALL_RECT rTemp = { 0 };
	control.GetRect(&rTemp);
	rTemp.Left = m_rRect.Left + x;
	rTemp.Top = m_rRect.Top + y;
	if (rTemp.Right + x > m_rRect.Right )
	{
		rTemp.Right = m_rRect.Right - x;
	}
	control.SetRect(&rTemp);

}

int CDrawBox::Proc(int lEvent, LPARAM lPar)
{
	return 1;
}

void CDrawBox::Show()
{

	//SMALL_RECT rc;

	BOOL bResult = FALSE;

	WORD att0, att1, attText;
	DWORD dwXx = 0;
	int i, chNum = strlen(m_szChar);

	att0 = BACKGROUND_INTENSITY; // 阴影属性

	att1 = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_BLUE;// 文本属性

	attText = FOREGROUND_RED | FOREGROUND_INTENSITY; // 文本属性

	int w = 4;										 // 设置阴影然后填充
	COORD posShadow = { m_rRect.Left + 1, m_rRect.Top + 1 }, posText = { m_rRect.Left, m_rRect.Top };



	//在绘制窗口前要先清场。
	if (m_wGeneral_color == 0) //获取最初始的颜色
	{
		ReadConsoleOutputAttribute(m_hOut, &m_wGeneral_color, 1, posShadow, &dwXx);
	}

	if (m_wGeneral_color != 0) //恢复初始颜色
	{
		COORD cTemp = { m_rRect.Left, m_rRect.Top };
		for (i = 0; i <= m_rRect.Bottom; i++ )
		{
			bResult = FillConsoleOutputAttribute(m_hOut, m_wGeneral_color, m_rRect.Right + 1, cTemp, &dwXx);
			//bResult = WriteConsoleOutputCharacterA(m_hOut, "a", m_rRect.Right, cTemp, &dwXx);
			bResult = FillConsoleOutputCharacterA(m_hOut,' ', m_rRect.Right + 1, cTemp, &dwXx);
			cTemp.Y++;

		}
	}
	

	for (i = 0; i < m_rRect.Bottom; i++)

	{
		bResult = FillConsoleOutputAttribute(m_hOut, att0, m_rRect.Right, posShadow, &dwXx);
		posShadow.Y++;
	}

	for (i = 0; i < m_rRect.Bottom; i++)

	{
		bResult = FillConsoleOutputAttribute(m_hOut, att1, m_rRect.Right, posText, &dwXx);
		posText.Y++;

	}


	//转化子控件左上角的相对距离为缓冲区坐标
// 	control.m_rRect.Left = m_rRect.Left + 2;
// 	control.m_rRect.Top = m_rRect.Top + 2;

	

	//bResult = WriteConsoleOutputCharacterA(m_hOut, m_szChar, strlen(m_szChar), posText, &dwXx);
	//这里要改为输出一个控件,在盒子控件内再输出别的控件

	//SetConsoleOutputCP(437);
	DrawBox();

	//SetConsoleTextAttribute(hOut, bInfo.wAttributes); // 恢复原来的属性
}

void CDrawBox::DrawBox() // 函数功能：画边框
{
	DWORD dwXx = 0;

	TCHAR chBox[8] = { 0 };
	//TCHAR chBox[] = L"┌┐└┘─│";
	COORD pos;

	swprintf_s(chBox, 8, L"%s", L"┏┓┗┛━┃-");

	//到这里来画所有内部控件

// 	for (std::list<CControl *>::iterator iter = child_control_info.begin(); iter != child_control_info.end(); iter ++)
// 	{
// 		//各个子控件显示,并给窗口控件设定宽高
// 		(*iter)->Show();
// 	}
// 	


	// 画边框的上 下边界

	pos.X = m_rRect.Left;
	pos.Y = m_rRect.Top;
	//画左上角
	FillConsoleOutputCharacter(m_hOut, chBox[0], 2, pos, &dwXx);
	pos.X = m_rRect.Left + 2;
	//画上边界
//	FillConsoleOutputCharacter(m_hOut, chBox[4], rc.Right -3 , pos, &dwXx);
	//画右上角
	pos.X = m_rRect.Left + m_rRect.Right - 2;
	FillConsoleOutputCharacter(m_hOut, chBox[1], 2, pos, &dwXx);
	

	pos.X = m_rRect.Left;
	//画左下角
	pos.Y = m_rRect.Top + m_rRect.Bottom - 1;
	FillConsoleOutputCharacter(m_hOut, chBox[2], 2, pos, &dwXx);
	//画下边界
	pos.X = m_rRect.Left + 2;
//	FillConsoleOutputCharacter(m_hOut, chBox[4], rc.Right - 3, pos, &dwXx);
	//画右下角
	pos.X = m_rRect.Left + m_rRect.Right - 2;
	FillConsoleOutputCharacter(m_hOut, chBox[3],2, pos, &dwXx);
	

}
//////////////////////////////////////////////////////////////////////////
//LIST列表控件
// 
CList::CList()
{
	m_rRect.Left = 0;
	m_rRect.Top = 0;
	//m_wGeneral_color = m_bInfo.wAttributes;
	m_wHighlight_color = FOREGROUND_GREEN |BACKGROUND_BLUE | FOREGROUND_INTENSITY| BACKGROUND_INTENSITY;
}
void CList::Show()
{
	DWORD dwXx = 0;
	COORD posShadow = { m_rRect.Left , m_rRect.Top };
	int i = 0;
	//在指定位置输出LIST中的内容
	for (std::list<char *>::iterator iter = m_lRow.begin(); iter != m_lRow.end(); iter ++)
	{
		int iSize = 0;
		iSize = strlen((char *)*iter);
		if (i == 0)
		{
			ReadConsoleOutputAttribute(m_hOut,&m_wGeneral_color, iSize, posShadow,&dwXx);
			FillConsoleOutputAttribute(m_hOut,m_wHighlight_color,iSize,posShadow,&dwXx);
			m_iItem = 0; //第一行高亮 
		}
		WriteConsoleOutputCharacterA(m_hOut,(char *)*iter,iSize, posShadow,&dwXx);
		posShadow.Y++;
		i++;
	}
	Set_Input_Event();
}
//添加的数据均独立内存保存，不用时需DEL释放
int CList::Add(char * buff)
{
	char * szBuff = nullptr;
	int listNum = 0;
	szBuff = new char[strlen(buff) + 1]();
	memcpy_s(szBuff, strlen(buff) + 1, buff, strlen(buff));
	listNum = m_lRow.size();
	m_lRow.push_back(szBuff);
	if (m_lRow.size() > listNum)
	{
		//成功添加一行后需要把右边和底边的相对距离增加
		if (m_rRect.Right < strlen(szBuff))
		{
			m_rRect.Right = strlen(szBuff);
		}
		m_rRect.Bottom = listNum; //底边就等于行数

		return listNum;
	}
	return -1;
}

void CList::Set_Input_Event()
{
	INPUT_RECORD keyrec;        //定义输入事件结构体  
	DWORD res;      //定义返回记录  
	for (;;)
	{
		ReadConsoleInput(m_hIn, &keyrec, 1, &res);      //读取输入事件  
		if (keyrec.EventType == KEY_EVENT && !keyrec.Event.KeyEvent.bKeyDown)      //如果当前事件是键盘事件  
		{
			switch (keyrec.Event.KeyEvent.wVirtualKeyCode )
			{
			case VK_UP:
				if (m_iItem > 0)
				{
					
					Highlight(-1);
					
					
				}
				break;
			case VK_DOWN:
				if (m_iItem < m_rRect.Bottom)
				{
					Highlight(1);
					
				}
				break;
			default:
				break;
			}
		}
	}
	return;
}

int CList::Proc(int lEvent, LPARAM lPar)
{
	MOUSE_EVENT_RECORD mouse = *(PMOUSE_EVENT_RECORD)lPar;


	m_iItem = (mouse.dwMousePosition.Y - m_rRect.Top);


	return 1;
}

void CList::Highlight(int i)
{
	DWORD dwXx = 0;
	COORD posShadow = { m_rRect.Left , m_rRect.Top + m_iItem };
	//恢复原来的行背景
	FillConsoleOutputAttribute(m_hOut, m_wGeneral_color, m_rRect.Right, posShadow, &dwXx);
	//m_iItem+=num;
	posShadow.Y = m_rRect.Top + m_iItem;
	FillConsoleOutputAttribute(m_hOut, m_wHighlight_color, m_rRect.Right, posShadow, &dwXx);
}
//////////////////////////////////////////////////////////////////////////
//输入框控件
CInput::CInput(char *buf, int x, int y, int weight, int height)
{
	sprintf_s(m_szChar, MAX_PATH, "%s:", buf);
	m_rRect.Left = x;
	m_rRect.Top = y;
	m_rRect.Right = weight;
	m_rRect.Bottom = height;
	m_iCursorPos.X = strlen(m_szChar) + 1 + m_rRect.Left;
	m_iCursorPos.Y = y;
}
CInput::CInput(int x, int y, int weight, int height)
{
	memset(m_szChar,0,MAX_PATH);
	m_rRect.Left = x;
	m_rRect.Top = y;
	m_rRect.Right = weight;
	m_rRect.Bottom = height;
	m_iCursorPos.X = strlen(m_szChar) + 1;
	m_iCursorPos.Y = y;
}
DWORD CInput::GetContentLen()
{
	return m_sContent.size();
}
void CInput::GetEditContent(char *buf, DWORD size)
{
	sprintf_s(buf, size, "%s", m_sContent.c_str());
}
int CInput::Proc(int lEvent, LPARAM lPar) //重写过程函数
{

	switch (lEvent)
	{
	case WM_MOUSEACTIVATE:
		break;
	case WM_KILLFOCUS: //失去键盘焦点时，需要关闭光标
		CONSOLE_CURSOR_INFO cur;
		cur.bVisible = false;
		cur.dwSize = 10;
		SetConsoleCursorInfo(m_hOut, &cur);
		break;
	case WM_CHAR: //接受字符，并保存
		//m_sContent.
	{
		DWORD dx = 0;
		PKEY_EVENT_RECORD key = (KEY_EVENT_RECORD *)lPar;

		if (key->wVirtualKeyCode = VK_BACK)
		{
			//删除退格
			//清除显示

			//光标回退一格

			//删除保存的字符

		}

		if ((WCHAR)key->uChar.UnicodeChar > 127)
		{
			char szTemp[3] = "";
			WideCharToMultiByte(CP_ACP,NULL, ((WCHAR *)&(key->uChar.UnicodeChar)),1,szTemp,2,nullptr,nullptr);
			m_sContent= m_sContent + szTemp;
			WriteConsoleOutputCharacterW(m_hOut, &(key->uChar.UnicodeChar), 1, m_iCursorPos, &dx);
			dx = 2;
		}
		else
		{
			m_sContent = m_sContent + key->uChar.AsciiChar;
			WriteConsoleOutputCharacterA(m_hOut, &key->uChar.AsciiChar, 1, m_iCursorPos, &dx);
			dx = 1;
		}
		
		
		
		if (m_iCursorPos.X + dx < m_rRect.Right)
		{
			m_iCursorPos.X +=dx;
		}
		else
		{
			m_iCursorPos.Y++;
			m_iCursorPos.X = strlen(m_szChar) + 1 + m_rRect.Left;
		}
		SetConsoleCursorPosition(m_hOut, m_iCursorPos);

		break;
	}
	case WM_LBUTTONDOWN: //激活输入框，显示光标
	{
		CONSOLE_CURSOR_INFO cur;
		cur.bVisible = TRUE;
		cur.dwSize = 10;

		SetConsoleCursorInfo(m_hOut, &cur);
		SetConsoleCursorPosition(m_hOut, m_iCursorPos);
			break;
	}
	default:
		break;
	}
	return 1;
}

void CInput::Show()
{
	COORD cTemp = { 0 };
	DWORD dx = 0;
	cTemp.X = m_rRect.Left;
	cTemp.Y = m_rRect.Top;
	WriteConsoleOutputCharacterA(m_hOut, m_szChar, strlen(m_szChar), cTemp, &dx);


}

void CInput::ShowFromInput()
{
	int row = 0;
	row = m_sContent.size() / (m_rRect.Right - strlen(m_szChar)) + 1;
	for (int i = 0; i < row ; i ++)
	{
		//按行输出


	}

}
//////////////////////////////////////////////////////////////////////////
CButton::CButton(char *buf, int x, int  y, int weight, int height)
{
	m_rRect.Left = x;
	m_rRect.Top = y;
	m_rRect.Right = weight;
	m_rRect.Bottom = height;
	sprintf_s(m_szChar, MAX_PATH, "%s", buf);
	//m_wGeneral_color = 0; //本来的颜色
	m_attDown = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | BACKGROUND_BLUE;
	m_attUp = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_RED | BACKGROUND_BLUE;
}
CButton::CButton(int x, int  y, int weight, int height)
{
	m_rRect.Left = x;
	m_rRect.Top = y;
	m_rRect.Right = weight;
	m_rRect.Bottom = height;
	//m_wGeneral_color = 0; //本来的颜色

	m_attDown = FOREGROUND_BLUE| FOREGROUND_GREEN | FOREGROUND_RED |BACKGROUND_BLUE;
	m_attUp = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_RED | BACKGROUND_BLUE;
}
void CButton::Show()
{
	COORD cTemp = { 0 };
	cTemp.X = m_rRect.Left;
	cTemp.Y = m_rRect.Top;
	DWORD dxx = 0;
	FillConsoleOutputAttribute(m_hOut, m_attUp, m_rRect.Right, cTemp, &dxx);
	WriteConsoleOutputCharacterA(m_hOut, m_szChar, m_rRect.Right, cTemp, &dxx);
}

int CButton::Proc(int lEvent, LPARAM lPar)
{
	COORD cTemp = { 0 };
	cTemp.X = m_rRect.Left;
	cTemp.Y = m_rRect.Top;
	DWORD dxx = 0;
	if (lEvent == WM_LBUTTONDOWN)
	{
		FillConsoleOutputAttribute(m_hOut, m_attDown, m_rRect.Right, cTemp, &dxx);
	}
	if (lEvent == WM_LBUTTONUP)
	{
		FillConsoleOutputAttribute(m_hOut, m_attUp, m_rRect.Right, cTemp, &dxx);
	}
	return 1; //并没有处理按下去后的事件
}


//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
//表格控件
CTable::CTable(int x, int  y, int weight, int height)
{
	m_rRect.Left = x;
	m_rRect.Top = y;
	m_rRect.Right = weight - 2;
	m_rRect.Bottom = height;
	m_wHighlight_color = FOREGROUND_GREEN | BACKGROUND_BLUE | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;
	m_iPos = 1;
	m_vScrollbar = TRUE;
	m_hScrollbar = TRUE; //默认没有滚动条
}
int CTable::Proc(int lEvent, LPARAM lPar)
{
	//表格控件点击，需要计算出，点的哪行，哪列
	switch (lEvent)
	{
	case WM_LBUTTONDOWN:
		MOUSE_EVENT_RECORD mouse = *(PMOUSE_EVENT_RECORD)lPar;
		//需判断是否点击的为滚动条区域

		Highlight(mouse.dwMousePosition.Y - m_rRect.Top);
		break;
	case WM_KEYDOWN:
		KEY_EVENT_RECORD  key = *(PKEY_EVENT_RECORD)lPar;
		//键盘按下消息
		switch (key.wVirtualKeyCode)
		{
		case VK_DOWN:
			Highlight(m_iItem + 1);
			break;
		case VK_UP:
			Highlight(m_iItem - 1);
			break;
		default:
			break;
		}

	case WM_VSCROLL:
		//滚动条消息
		switch ((int)lPar)
		{
		case SB_LINEUP:
			if (m_iPos > 1)
			{
				m_iPos--;
				Show();
			}
			
			break;
		case SB_LINEDOWN:
			if (m_iPos < m_iMax)
			{
				m_iPos++;
				Show();
			}
			
			
			break;
		default:
			break;
		}
		break;
	default:
		break;
	}
	

	return 1;
}
void CTable::Highlight(int i)
{
	if ( i == 0 || i > m_rRect.Bottom -1 )
	{
		return;
	}
	DWORD dwXx = 0;
	COORD posShadow = { m_rRect.Left , m_rRect.Top + m_iItem };
	//恢复原来的行背景
	FillConsoleOutputAttribute(m_hOut, m_wGeneral_color, m_rRect.Right - 2, posShadow, &dwXx);
	m_iItem = i;
	posShadow.Y = m_rRect.Top + m_iItem;
	FillConsoleOutputAttribute(m_hOut, m_wHighlight_color, m_rRect.Right - 2, posShadow, &dwXx);
	
}
int CTable::AddCol(int w, char * title) //添加列
{
// 	if ((*(llColInfo.begin()))->szCol.size() > 0)
// 	{
// 		return -1; //已经有行内容，无法再添加列
// 	}

	PCOLUMN_INFO colInfo = new COLUMN_INFO();
	if (!colInfo)
	{
		return -1;
	}
	colInfo->iColID = llColInfo.size();
	colInfo->iColWeight = w;
	sprintf_s(colInfo->szColTitle, 50, "%s", title); //记录列标题

	llColInfo.push_back(colInfo);

	//需要增加表格宽度
	//m_rRect.Right += w;
	
	return 0;
	
}
int CTable::AddRow() //增加行
{
	//需要在每列LIST里面增加一格内容
	int iRow = -1;
	for (std::list<PCOLUMN_INFO>::iterator iterCol = llColInfo.begin(); iterCol != llColInfo.end(); iterCol ++ )
	{

		(*iterCol)->szCol.push_back(NULL); //增加一个空指针，因为还没有内容
		iRow = (*iterCol)->szCol.size() - 1;

	}
// 	if (iRow > 0)
// 	{
// 		m_rRect.Bottom++;
// 	}
	
	return iRow;
}
void CTable::SetRowTitle(int row, int col, char * szBuff)//设置行内容
{
	int iRow = 0;
	int iCol = 0;
	for (std::list<PCOLUMN_INFO>::iterator iterCol = llColInfo.begin(); iterCol != llColInfo.end(); iterCol++)
	{
		if (iCol == col)
		{
			//需要在此列增加内容

			for (std::list<char *>::iterator iterRow = (*iterCol)->szCol.begin(); iterRow != (*iterCol)->szCol.end(); iterRow++)
			{
				//这里是每一列的行格子内容
				if (iRow == row) //需要在此行增加内容
				{
					(*iterRow) = new char[strlen(szBuff) + 1]();
					sprintf_s((*iterRow), strlen(szBuff) + 1,"%s",szBuff);
					return;
				}
				iRow++;
			}


		}
	


		iCol++;
	}


	return;
}
void CTable::Show()
{
	COORD cTemp = {m_rRect.Left,m_rRect.Top};
	DWORD dwXx = 0;
	int iTem = 0; //控制显示的行数
	int iStart = 0;//控制显示开始的行数
	int weight = m_rRect.Right;
	int iii = 0;
	if (m_vScrollbar)
	{
		weight = m_rRect.Right - 2; //主体内容显示的宽度，需要减掉滚动条位置
		iii =(int) ceil((float)((*(llColInfo.begin()))->szCol.size()) / (float)(m_rRect.Bottom - 2));
		m_iMax = m_rRect.Bottom - 2; //取表格行数
	}

	ReadConsoleOutputAttribute(m_hOut,&m_wGeneral_color,1,cTemp,&dwXx);

	//需要在高度上加1 容纳 表头
	for (std::list<PCOLUMN_INFO>::iterator iterCol = llColInfo.begin(); iterCol != llColInfo.end(); iterCol++)
	{

			//输出表头
		cTemp.Y = m_rRect.Top;
		iTem = 1;
		iStart = 1;
		WriteConsoleOutputCharacterA(m_hOut, (char *)(*iterCol)->szColTitle,strlen((char *)(*iterCol)->szColTitle) /*(*iterCol)->iColWeight*/, cTemp, &dwXx);
		cTemp.Y++;


		//这里需要修改显示方法：显示的开始行数，需要通过滚动条来确定
		for (std::list<char *>::iterator iterRow = (*iterCol)->szCol.begin(); TRUE; )
		{
			dwXx = (*iterCol)->iColWeight; //临时用来保存下要写入的长度
			
			if (iTem < m_rRect.Bottom && iterRow == (*iterCol)->szCol.end())
			{
				FillConsoleOutputCharacterA(m_hOut, ' ', dwXx, cTemp, &dwXx);
				cTemp.Y++;
				iTem++;
			}
			else if (iTem < m_rRect.Bottom && iterRow != (*iterCol)->szCol.end())
			{
				if (iStart > (m_iPos - 1) * iii)
				{
					FillConsoleOutputCharacterA(m_hOut, ' ', dwXx, cTemp, &dwXx);
					if (strlen((char *)*iterRow) < dwXx)
					{
						dwXx = strlen((char *)*iterRow);
					}
					WriteConsoleOutputCharacterA(m_hOut, (char *)*iterRow, dwXx, cTemp, &dwXx); //写入空值，

					cTemp.Y++;

					iTem++;
				}
				iterRow++;
			}else if (iTem >= m_rRect.Bottom)
			{
				break;
			}



			
			
			iStart++;
		}
		cTemp.X += (*iterCol)->iColWeight;
		
	}
	ScrollbarShow(); //滚动条显示
}
void CTable::SetRect(SMALL_RECT *re)
{
	m_rRect.Left = re->Left;
	m_rRect.Top = re->Top;
	m_rRect.Right = re->Right;
	m_rRect.Bottom = re->Bottom;

}
//////////////////////////////////////////////////////////////////////////
CScroll::CScroll(int x, int y, int w)
{
	m_rRect.Left = x;
	m_rRect.Top = y;
	iPos =1;
	m_rRect.Right = 2;
	m_rRect.Bottom = w + 2;
	sprintf_s(m_szChar, MAX_PATH, "*");
	m_wGeneral_color = FOREGROUND_INTENSITY |FOREGROUND_GREEN |BACKGROUND_INTENSITY;
	m_wHighlight_color = FOREGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY;
}

void CScroll::Show()
{
	COORD cTemp = { 0 };
	cTemp.X = m_rRect.Left;
	cTemp.Y = m_rRect.Top;
	DWORD dwXx = 0;
	for (int i = 0; i< m_rRect.Bottom; i++)
	{
		if (i == iPos)
		{
			FillConsoleOutputAttribute(m_hOut, m_wHighlight_color, 2, cTemp, &dwXx);
 			WriteConsoleOutputCharacterW(m_hOut, L"▓", 1, cTemp, &dwXx);
		}
		else
		{
			WriteConsoleOutputCharacterW(m_hOut, L" ", 1, cTemp, &dwXx);
			FillConsoleOutputAttribute(m_hOut, m_wGeneral_color, 2, cTemp, &dwXx);
		}
		if (i == 0)
		{
			WriteConsoleOutputCharacterA(m_hOut, "△", 2, cTemp, &dwXx);
		}
		if (i == m_rRect.Bottom - 1)
		{
			WriteConsoleOutputCharacterA(m_hOut, "▽", 2, cTemp, &dwXx);
		}
		cTemp.Y++;
	}
}

int CScroll::Proc(int lEvent, LPARAM lPar)
{
	switch (lEvent)
	{
	case WM_LBUTTONDOWN: //按了鼠标
		//判断是在划块上方还是下方点击
		MOUSE_EVENT_RECORD mouse = *(PMOUSE_EVENT_RECORD)lPar;
		if (mouse.dwMousePosition.Y - m_rRect.Top > iPos)
		{
			if (iPos < m_rRect.Bottom - 2)
			{
				iPos++;
			}
		}else if (mouse.dwMousePosition.Y - m_rRect.Top < iPos && mouse.dwMousePosition.Y - m_rRect.Top > 0)
		{
			if (iPos > 1)
			{
				iPos--;
			}

		}
		Show();
		break;
	default:
		break;
	}
	return 1;
}
////////// 
CConsole::CConsole()
{
	m_hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	m_hIn = GetStdHandle(STD_INPUT_HANDLE);
	m_bInfo.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
	GetConsoleScreenBufferInfoEx(m_hOut, &m_bInfo);
	
	COORD cTemp = { 0 };
	DWORD dxx = 0;
	//m_bCursonInfo.dwSize = 10;
	//m_bCursonInfo.bVisible = FALSE;
	//SetConsoleCursorInfo(m_hOut, &m_bCursonInfo);
	m_bInfo.wAttributes = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
	SetConsoleScreenBufferInfoEx(m_hOut,&m_bInfo);
	//FillConsoleOutputAttribute(m_hOut, FOREGROUND_BLUE| 0, m_bInfo.dwSize.X * m_bInfo.dwSize.Y, cTemp, &dxx);
	Init();
	
}
//此ADD中添加各控件
CControl *CConsole::Add(char *classNmae, char *title, int x, int y, int weight, int height)
{
	PCONTROL_BASE_INFO controlName = new CONTROL_BASE_INFO();
	CControl *name = NULL;
	if (strcmp(classNmae,"CStaticText") == 0)
	{		
		name = (CControl*) new CStaticText(title,x,y,weight,height);	
		controlName->z = 2;
	}else if (strcmp(classNmae, "CTable") == 0)
	{
		name = (CControl*) new CTable(x, y, weight, height);
		controlName->z = 1;
	}
	else if (strcmp(classNmae, "CDrawBox") == 0)
	{
		name = (CControl*) new CDrawBox(x, y, weight, height);
		controlName->z = 0;
	}
	else if (strcmp(classNmae, "CButton") == 0)
	{
		name = (CControl*) new CButton(title,x, y, weight, height);
		controlName->z = 0;
	}
	else if (strcmp(classNmae,"CScroll") == 0)
	{
		name = (CControl*) new CScroll(x, y, height);
		controlName->z = 1;

	} else if (strcmp(classNmae, "CInput") == 0)
	{
		name = (CControl*) new CInput(title,x, y,weight ,height);
		controlName->z = 2;
	}
	else
	{
		std::cout << "错误的类名" << std::endl;
	}
	controlName->iControlId = (int)name;
	controlName->rRect.Left = x;
	controlName->rRect.Top = y;
	controlName->rRect.Right =  weight;
	controlName->rRect.Bottom = height;
	
	control_info_list.push_back(controlName);

	return name;
}

void CConsole::Set_Input_Event()
{
	INPUT_RECORD keyrec;        //定义输入事件结构体
	DWORD res;      //定义返回记录
	char eve[20] = "";
	SMALL_RECT rTemp = { 0 };
	int cid;
	unsigned long x1 = 0x00780000;
	unsigned long x2 = 0xff880000;
	WCHAR wchar;
	char gchar[3];
	std::string text;//

	COORD xx = { 0 };
	DWORD xx2 = 0;

	for (;;)
	{
		int i;
		ReadConsoleInput(m_hIn, &keyrec, 1, &res);      //读取输入事件
		
		//无意义的消息，退出 ,有意义的消息分派
		switch (keyrec.EventType)
		{
		case MOUSE_EVENT:
			cid = FocusTest(&keyrec.Event.MouseEvent.dwMousePosition);
			if (cid == -1)
			{
				continue;
			}
			
			i = 0;
			if (keyrec.Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED && keyrec.Event.MouseEvent.dwEventFlags == 0)
			{
				((CControl *)cid)->GetRect(&rTemp);
				if (keyrec.Event.MouseEvent.dwMousePosition.X > rTemp.Left + rTemp.Right - 3)
				{
					//这是一个滚动条消息
					if (keyrec.Event.MouseEvent.dwMousePosition.Y - rTemp.Top + 1 > ((CControl *)cid)->GetScrollBlock())
					{
						((CControl *)cid)->Proc(WM_VSCROLL, SB_LINEDOWN);
						break;
					}
					if (keyrec.Event.MouseEvent.dwMousePosition.Y - rTemp.Top + 1< ((CControl *)cid)->GetScrollBlock())
					{
						((CControl *)cid)->Proc(WM_VSCROLL, SB_LINEUP);
					}
						
					break;
				}
				else
				{
					//鼠标按下
					//WM_KILLFOCUS 对上一个激活的控件发失去焦点消息
					((CControl *)cid)->Proc(WM_KILLFOCUS, NULL);

					//对当前控件发鼠标消息，激活
					((CControl *)cid)->Proc(WM_LBUTTONDOWN, (LPARAM)&keyrec.Event.MouseEvent);
					m_activated = cid; //保存当前被鼠标点击的控件
					break;
				}
				
			}
			if (keyrec.Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED && keyrec.Event.MouseEvent.dwEventFlags == 1)
			{
				//左键按住不放
				((CControl *)cid)->GetRect(&rTemp);
				if (keyrec.Event.MouseEvent.dwMousePosition.X > rTemp.Left + rTemp.Right - 3)
				{

					//这是一个滚动条消息
					if (keyrec.Event.MouseEvent.dwMousePosition.Y - rTemp.Top + 1 > ((CControl *)cid)->GetScrollBlock())
					{
						((CControl *)cid)->Proc(WM_VSCROLL, SB_LINEDOWN);
						break;
					}
					if (keyrec.Event.MouseEvent.dwMousePosition.Y - rTemp.Top + 1 < ((CControl *)cid)->GetScrollBlock())
					{
						((CControl *)cid)->Proc(WM_VSCROLL, SB_LINEUP);
					}

					break;
				}
				else
				{
					//鼠标按下
					//WM_KILLFOCUS 对上一个激活的控件发失去焦点消息
					((CControl *)cid)->Proc(WM_KILLFOCUS, NULL);

					//对当前控件发鼠标消息，激活
					((CControl *)cid)->Proc(WM_LBUTTONDOWN, (LPARAM)&keyrec.Event.MouseEvent);
					m_activated = cid; //保存当前被鼠标点击的控件
				}
				break;
			}
			if (keyrec.Event.MouseEvent.dwEventFlags == 0 && keyrec.Event.MouseEvent.dwEventFlags == 0)
			{
				//鼠标弹起
				//转为自定义消息
				//sprintf_s(eve, 20, "鼠标弹起:%d\n", keyrec.Event.MouseEvent.dwButtonState);
				//OutputDebugStringA(eve);
				((CControl *)cid)->Proc(WM_LBUTTONUP, (LPARAM)&keyrec.Event.MouseEvent);
			}

			if (keyrec.Event.MouseEvent.dwEventFlags == MOUSE_WHEELED  &&  keyrec.Event.MouseEvent.dwButtonState == x2)
			{
				//下滚轮
				//转为自定义消息
				//sprintf_s(eve, 20, "鼠标弹起:%d\n", keyrec.Event.MouseEvent.dwButtonState);
				//OutputDebugStringA(eve);
				((CControl *)cid)->Proc(WM_VSCROLL, SB_LINEDOWN);
				break;
			}
			
			if (keyrec.Event.MouseEvent.dwEventFlags == MOUSE_WHEELED  &&keyrec.Event.MouseEvent.dwButtonState == x1)
			{
				//上滚轮
				//转为自定义消息
				//sprintf_s(eve, 20, "鼠标弹起:%d\n", keyrec.Event.MouseEvent.dwButtonState);
				//OutputDebugStringA(eve);
				((CControl *)cid)->Proc(WM_VSCROLL, SB_LINEUP);
				break;
			}

			
			break;
 		case KEY_EVENT:
// 			//键盘消息，将被发送到激活的控件上面
			if (m_activated == NULL)
			{
				continue;
			}
			switch (keyrec.Event.KeyEvent.bKeyDown)
			{
			case TRUE:
				if (keyrec.Event.KeyEvent.uChar.UnicodeChar > 0) //字符事件
				{
					((CControl *)m_activated)->Proc(WM_CHAR, (LPARAM)&keyrec.Event.KeyEvent);
					break;
				}
				((CControl *)m_activated)->Proc(WM_KEYDOWN, (LPARAM)&keyrec.Event.KeyEvent);
				break;
			case FALSE:
				((CControl *)m_activated)->Proc(WM_KEYUP, (LPARAM)&keyrec.Event.KeyEvent);
 				break;
 			default:
				break;
			}
			
		default:
			break;
		}
	}
	return;
}

int CConsole::FocusTest(COORD *cr)
{
	char sz[40] = "";
	sprintf_s(sz, 40, "点击范围：%d,%d\n", cr->X, cr->Y);
	OutputDebugStringA(sz);
	SMALL_RECT sr = { 0 };
	//逆序 迭代器

	for (std::list<PCONTROL_BASE_INFO>::reverse_iterator  iter = control_info_list.rbegin(); iter != control_info_list.rend(); ++iter)
	{
		//((CControl *)(*iter)->iControlId)->Show();
		((CControl *)(*iter)->iControlId)->GetRect(&sr);
		sprintf_s(sz, 40, "控件范围：%d,%d--%d,%d\n", sr.Left, sr.Top, sr.Left + sr.Right - 1, sr.Top + sr.Bottom - 1);
		OutputDebugStringA(sz);

		if (cr->X >= sr.Left && cr->X <= (sr.Left + sr.Right - 1) && cr->Y >= sr.Top && cr->Y <= (sr.Top + sr.Bottom - 1))
		{
			return (int)((CControl *)(*iter)->iControlId);
		}
	}
	return -1;
}
//所有事件在此处理
//操作的控件ID，当前控件上的坐标焦点，
void CConsole::EventPro(int cid, int levent, void *la, void *par)
{
	switch (levent)
	{
	case ControlLfClick: //左键被点击

		break;

	default:
		break;
	}

	//Show();
	return;
}

BOOL CConsole::comp_sort(const _CONTROL_BASE_INFO *node1, const _CONTROL_BASE_INFO *node2)
{
	return node1->z < node2->z;
}
//显示容器内所有控件
void CConsole::Show()
{
	//从控件列表中所有控件都显示
	//排序下，以免有遮挡
	control_info_list.sort(&(CConsole::comp_sort));




	for (std::list<PCONTROL_BASE_INFO>::iterator iter = control_info_list.begin(); iter != control_info_list.end(); iter ++)
	{
		((CControl *)(*iter)->iControlId)->Show();

	}
	return;
}

void CConsole::Init()
{

	DWORD aa = 0;
	GetConsoleMode(m_hIn, &aa);
	

//  	CTable *table1  = (CTable *)Add("CTable", "这是一个文本控件", 5, 10,70,22);
// 	table1->AddCol(10, "ID");
// 	table1->AddCol(10, "姓名");
// 	table1->AddCol(10, "分数");
// 	table1->AddCol(10, "年纪");
// 	table1->AddCol(10, "性别");
// 	table1->AddCol(10, "班级");
// 	char sz[5] = "";
// 	for (int i = 0,j=0; i < 100 ; i++)
// 	{
// 		j = table1->AddRow();
// 		sprintf_s(sz, 5, "%d", i);
// 		table1->SetRowTitle(j, 0, sz);
// 		table1->SetRowTitle(j, 1, "小李");
// 		table1->SetRowTitle(j, 2, "70");
// 		table1->SetRowTitle(j, 3, "小李");
// 		table1->SetRowTitle(j, 4, "70");
// 		table1->SetRowTitle(j, 5, "小李");
// 	}
	

	//table1.Show();
	//CStaticText *text1 = (CStaticText *) Add("CStaticText", "这是一个文本控件", 10, 10,10,1);
	//text1->SetTitle("修改过的文本");
	//CDrawBox *box1 =(CDrawBox *) Add("CDrawBox", "表格1", 10, 10,75,30);
	//box1->Inset(*table1,3,2);
	//CButton button1 = *(CButton *)Add("CButton", "按钮1", 5, 1, 5, 1);

	CInput *input1 = (CInput *)Add("CInput", "这是编辑框", 5, 10, 70, 22);
}
